0.1 Análisis de patrones de puntos

Las técnicas de análisis de patrones de puntos analizan la distribución de eventos geolocalizados que surgen al azar. La diferencia fundamental con otros análisis que comprenden también el uso de localizaciones (como las temperaturas mínimas medidas por estaciones meteorológicas) es que en este caso los puntos representan eventos conocidos y aleatorios (por ejemplo, los crímenes ocurridos en una ciudad, accidentes de tráfico o incendios en una región). A diferencia de otros eventos, como el ejemplo de las temperaturas mínimas, la ausencia de datos no se debe a la ausencia de medición (e.g. no existe una estación meteorológica en ese lugar), si no a que no se ha producido el evento en dicha localización.

Objetivo de aprendizaje:

El alumno debe ser capaz de conocer los datos de tipo patrones de punto, identificarlos y representarlos adecuadamente.

Tarea 1: Abrimos RStudio

El presente análisis se va a realizar empleando RStudio, por lo que empezaremos abriendo el programa y creando un nuevo script de R en Proyecto>File>New File>R script.

Tarea 2: Importamos y describimos los datos objeto de estudio

El primer paso consiste en importar la base de datos de crímenes en la ciudad de Valencia. El archivo está en formato csv, por lo que usaremos el paquete readr para importar los datos:

library(readr)
library(dplyr)

# En este caso el archivo está en la carpeta "data" de nuestro proyecto
crimen <- read_csv("data/crime-data-Valencia.csv")


summary(crimen)
#>    crime_id          crime_date         crime_time        crime_type       
#>  Length:90247       Length:90247       Length:90247      Length:90247      
#>  Class :character   Class :character   Class1:hms        Class :character  
#>  Mode  :character   Mode  :character   Class2:difftime   Mode  :character  
#>                                        Mode  :numeric                      
#>                                                                            
#>                                                                            
#>      muni                year          month             week      
#>  Length:90247       Min.   :2010   Min.   : 1.000   Min.   : 1.00  
#>  Class :character   1st Qu.:2013   1st Qu.: 4.000   1st Qu.:14.00  
#>  Mode  :character   Median :2016   Median : 7.000   Median :27.00  
#>                     Mean   :2015   Mean   : 6.537   Mean   :26.65  
#>                     3rd Qu.:2018   3rd Qu.: 9.000   3rd Qu.:38.00  
#>                     Max.   :2020   Max.   :12.000   Max.   :53.00  
#>       day           week_day     week_day_name        crime_hour   
#>  Min.   :  1.0   Min.   :1.000   Length:90247       Min.   : 0.00  
#>  1st Qu.: 96.0   1st Qu.:3.000   Class :character   1st Qu.: 5.00  
#>  Median :187.0   Median :5.000   Mode  :character   Median :14.00  
#>  Mean   :183.6   Mean   :4.323                      Mean   :12.52  
#>  3rd Qu.:266.0   3rd Qu.:6.000                      3rd Qu.:19.00  
#>  Max.   :366.0   Max.   :7.000                      Max.   :23.00  
#>    crime_lon         crime_lat        atm_dist          bank_dist       
#>  Min.   :-0.4296   Min.   :39.42   Min.   :   1.549   Min.   :   1.713  
#>  1st Qu.:-0.3883   1st Qu.:39.46   1st Qu.: 380.535   1st Qu.: 133.908  
#>  Median :-0.3749   Median :39.47   Median : 630.867   Median : 228.003  
#>  Mean   :-0.3724   Mean   :39.47   Mean   : 790.228   Mean   : 305.315  
#>  3rd Qu.:-0.3593   3rd Qu.:39.48   3rd Qu.: 986.897   3rd Qu.: 384.706  
#>  Max.   :-0.3208   Max.   :39.53   Max.   :4838.847   Max.   :3411.537  
#>     bar_dist          cafe_dist        industrial_dist   market_dist      
#>  Min.   :   0.489   Min.   :   1.342   Min.   :   0.1   Min.   :   1.821  
#>  1st Qu.: 149.879   1st Qu.: 133.274   1st Qu.: 268.4   1st Qu.: 487.874  
#>  Median : 292.246   Median : 264.504   Median : 509.6   Median : 869.516  
#>  Mean   : 392.072   Mean   : 360.275   Mean   : 675.2   Mean   :1008.414  
#>  3rd Qu.: 507.701   3rd Qu.: 462.982   3rd Qu.: 909.9   3rd Qu.:1263.405  
#>  Max.   :4352.380   Max.   :4237.915   Max.   :4703.9   Max.   :4855.407  
#>  nightclub_dist      police_dist          pub_dist        restaurant_dist   
#>  Min.   :   1.189   Min.   :   0.688   Min.   :   1.489   Min.   :   0.427  
#>  1st Qu.: 468.164   1st Qu.: 455.810   1st Qu.: 190.150   1st Qu.:  73.401  
#>  Median : 810.185   Median : 706.094   Median : 383.330   Median : 147.797  
#>  Mean   : 930.501   Mean   : 875.246   Mean   : 496.472   Mean   : 223.875  
#>  3rd Qu.:1256.269   3rd Qu.:1105.625   3rd Qu.: 665.599   3rd Qu.: 272.288  
#>  Max.   :4700.567   Max.   :4765.745   Max.   :4168.869   Max.   :3746.536  
#>    taxi_dist           grid_id         grid_lon          grid_lat    
#>  Min.   :   2.441   Min.   :  8.0   Min.   :-0.4288   Min.   :39.42  
#>  1st Qu.: 393.438   1st Qu.:173.0   1st Qu.:-0.3898   1st Qu.:39.46  
#>  Median : 651.644   Median :215.0   Median :-0.3731   Median :39.47  
#>  Mean   : 717.381   Mean   :210.8   Mean   :-0.3724   Mean   :39.47  
#>  3rd Qu.: 931.083   3rd Qu.:248.0   3rd Qu.:-0.3620   3rd Qu.:39.48  
#>  Max.   :4284.239   Max.   :398.0   Max.   :-0.3230   Max.   :39.53

Q1. ¿Qué información contiene nuestros datos?

Este archivo contiene en total 90.247 registros, y proporciona 28 campos asociados a cada registro.

Entre los campos disponibles, destacamos los campos crime_lon y crime_lat: Son las coordenadas en las que se produjo el crimen.

Q2: ¿En qué CRS se encuentran las coordenadas?

Si nos fijamos, las coordenadas parecen corresponder con longitudes y latitudes, ya que como se explicó el rango posible de valores es \([-180, 180]\) (para longitudes) y \([-90, 90]\) (para latitudes):

Table 1: Crímenes en Valencia; Coordenadas
crime_lon crime_lat
-0.3826325 39.46332
-0.3906850 39.43517
-0.3747971 39.47927
-0.3992082 39.47982
-0.3596011 39.46740
-0.3552423 39.47461

Por lo tanto, podemos convertir la tabla en un objecto sf teniendo en cuenta esta información. A modo de recordatorio, el CRS correspondiente a coordenadas geográficas longitud/latitud es EPSG:4326.


library(sf)
# Objeto sf sin CRS

crimen_sf <- st_as_sf(
  crimen,
  coords = c(
    "crime_lon",
    "crime_lat"
  ),
  crs = st_crs(4326)
)

# Comprobamos con un mapa base

library(mapSpain)
library(ggplot2)

# Usamos imagen como mapa de fondo
tile <- esp_getTiles(crimen_sf, "IDErioja",
  zoommin = 1,
  crop = TRUE
)

ggplot() +
  layer_spatraster(tile) +
  geom_sf(
    data = crimen_sf,
    col = "blue",
    size = 0.3,
    alpha = 0.3
  )
Crímenes en Valencia

Figure 1: Crímenes en Valencia

Q3: ¿Hay algún patrón en la ocurrencia de crímenes?

En la Fig. 1 podemos intuir ciertos patrones en la ocurrencia de crímenes. Por ejemplo, parecen concentrarse en zonas céntricas y no hay crímenes registrados en la zona del puerto.

Para el siguiente análisis, vamos a analizar el patrón de crímenes del año 2010.

crimen_2010_sf <- crimen_sf %>%
  filter(
    year == "2010"
  )

ggplot() +
  layer_spatraster(tile) +
  geom_sf(
    data = crimen_2010_sf,
    col = "blue",
    size = 0.3,
    alpha = 0.3
  )
Crímenes en Valencia (2010)

Figure 2: Crímenes en Valencia (2010)

Tarea 3: Análisis de patrones con spatstat

El paquete spatstat (Baddeley & Turner (2005)) es el paquete de referencia cuando se trabaja con patrones de puntos

Siguiendo el anterior ejemplo, vamos a analizar el patrón de crímenes en el año 2010. Además, en el análisis de patrones de puntos es necesario delimitar la ventana espacial de observación (owin). En este caso será el municipio de Valencia.


# Extraigo Valencia con mapSpain

valencia <- esp_get_munic(munic = "^Valencia$") %>%
  # Necesito proyectar, en este caso usamos ETRS89-UTM huso 30 EPSG:25830
  st_transform(25830)



library(spatstat)
# Necesitamos un recinto de observación: owin

val_owin <- as.owin(valencia)

# Extraemos las coordenadas de los crímenes. Han de estar en el mismo CRS
# que el owin

coords <- crimen_2010_sf %>%
  st_transform(25830) %>%
  st_coordinates()

mydata_ppp <- ppp(
  x = as.numeric(coords[, 1]),
  y = as.numeric(coords[, 2]),
  window = val_owin
)

plot(mydata_ppp)

Q4. ¿Qué información contiene nuestro objeto en formato ppp?

summary(mydata_ppp)
#> Planar point pattern:  5332 points
#> Average intensity 3.917619e-05 points per square unit
#> 
#> *Pattern contains duplicated points*
#> 
#> Coordinates are given to 1 decimal place
#> i.e. rounded to the nearest multiple of 0.1 units
#> 
#> Window: polygonal boundary
#> 4 separate polygons (no holes)
#>            vertices      area relative.area
#> polygon 1         4   1977930       0.01450
#> polygon 2        82 131953000       0.97000
#> polygon 3         7    958085       0.00704
#> polygon 4         7   1214060       0.00892
#> enclosing rectangle: [720573.4, 735116.6] x [4351274, 4382995] units
#>                      (14540 x 31720 units)
#> Window area = 136103000 square units
#> Fraction of frame area: 0.295
#> 
#> *** 6 illegal points stored in attr(,"rejects") ***

Tarea 5: Cálculo de la densidad mediante cuadrantes.

Es importante determinar si los puntos se distribuyen al azar o tienen algún patrón. Por ello, lo primero que haremos será representar el objeto feb_ppp y superponer unos cuadrantes para su comportamiento (véase 3).

## Hallamos los cuadrantes
cuadrante <- quadratcount(mydata_ppp,
  nx = 5,
  ny = 5
)

## Dibujamos el número de crímenes que hay en cada cuadrante
plot(mydata_ppp, pch = 1, main = "")
plot(cuadrante, add = TRUE, col = "red", cex = 1.2)
Crímenes en Valencia por cuadrantes (2010)

Figure 3: Crímenes en Valencia por cuadrantes (2010)

Como se puede apreciar en la Fig. 3 hay cuadrantes que registran cero crímenes y otros que registran hasta 2.860 crímenes.

Tarea 6: Estimación de la densidad de patrones de puntos.

En la Fig. 4 se muestra la gráfica de la estimación usando la K de Ripley. Los conocimientos teóricos necesarios para llevar a cabo este tipo de estimación se verán en el tema Patrones de Puntos. El objetivo de este ejemplo es meramente ilustrativo.

densidad <- density(mydata_ppp)
plot(densidad, main = " ")
points(mydata_ppp, pch = "+", cex = 0.5)
Intensidad de crímenes estimada con la K-Ripley

Figure 4: Intensidad de crímenes estimada con la K-Ripley

Baddeley, A., & Turner, R. (2005). spatstat: An R package for analyzing spatial point patterns. Journal of Statistical Software, 12(6), 1–42. https://doi.org/10.18637/jss.v012.i06